package cn.song.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Collections;

/**
 * 请求转发控制器
 *
 * @author SongRenShuo
 * @date 2024/05/20
 */
@Slf4j
@RestController
public class ApiController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 转发请求至指定URL
     *
     * @param request    当前请求对象，用于获取转发目标URL
     * @param headers    要转发的HTTP头信息
     * @param formParams 转发时携带的表单参数
     * @param body       POST或PUT请求时的请求体
     * @return 转发操作的结果响应
     */
    @RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.PATCH, RequestMethod.OPTIONS, RequestMethod.HEAD, RequestMethod.TRACE})
    public ResponseEntity<String> forwardRequestSamePath(HttpServletRequest request,
                                                         @RequestHeader HttpHeaders headers,
                                                         @RequestParam MultiValueMap<String, String> formParams,
                                                         @RequestBody(required = false) String body) {
        // 获取请求的URI路径
        String basePath = request.getRequestURI();
        // 获取上下文路径长度，用于去除basePath中的contextPath部分
        int contextPathLength = request.getContextPath().length();
        // 假设目标基础URL作为参数传递
        String targetBaseUrl = request.getParameter("targetBaseUrl");
        if (targetBaseUrl == null) {
            return ResponseEntity.badRequest().body("缺少 'targetBaseUrl' 参数");
        }

        // 构建完整的目标URL，移除basePath中的contextPath部分并拼接targetBaseUrl
        String targetUrl = targetBaseUrl + basePath.substring(contextPathLength);

        HttpMethod method = HttpMethod.resolve(request.getMethod());
        if (method == null) {
            return ResponseEntity.badRequest().body("无效的HTTP方法");
        }

        HttpEntity<?> requestEntity = (HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method))
                ? (body != null && !body.isEmpty() ? new HttpEntity<>(body, headers) : new HttpEntity<>(formParams, headers))
                : new HttpEntity<>(headers);

        if (HttpMethod.GET.equals(method) && !formParams.isEmpty()) {
            targetUrl = UriComponentsBuilder.fromUriString(targetUrl).queryParams(formParams).toUriString();
        }

        log.info("请求转发开始, 目标URL: {}, 方法: {}, 请求数据: {}, 头部信息: {}", targetUrl, method, body != null ? body : formParams, headers);

        try {

            // 设置请求和响应的编码为utf-8
            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            // 设置请求头中的Accept-Charset为utf-8
            headers.setAcceptCharset(Collections.singletonList(StandardCharsets.UTF_8));

            ResponseEntity<String> responseEntity = restTemplate.exchange(targetUrl, method, requestEntity, String.class);
            log.info("请求转发结束, 目标URL: {}, 方法: {}, 请求数据: {}, 头部信息: {}, 响应: {}", targetUrl, method, body != null ? body : formParams, headers, responseEntity.getBody());
            return responseEntity;
        } catch (HttpClientErrorException ex) {
            log.error("请求转发失败(响应非200), 目标URL: {}, 方法: {}, 原因: {}", targetUrl, method, ex.getMessage());
            return ResponseEntity.status(ex.getStatusCode()).body(ex.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("请求转发失败, 目标URL: {}, 方法: {}, 原因: {}", targetUrl, method, e.getMessage());
            return ResponseEntity.status(500).body("请求转发时发生错误:" + e.getMessage());
        }
    }
}
